/*****************************************************************
*
*	Netcare Agent Project
*		Copyright(C) 2010, Wicresoft EKA. All Rights Reserved.
*
*	Authors:
*		Miles Chen (milesch@wicresoft.com)
*		TingRong Shi (trshi@wicresoft.com)
*
*	Part of the product code depends on gSOAP under GPL license
*		Copyright(C) 2000-2010, Robert van Engelen, Genivia Inc. All Rights Reserved.
*
*****************************************************************/
#include <fstream>
#include <string>

#ifdef WIN32
// Windows
#include <Windows.h>
#include <tchar.h>
#else
// Linux
#include <sys/utsname.h>
#endif

#include "SystemInfo.h"
#include "Log.h"

NETCARE_AGENT;

USING_STD;

#define SI_MAX_SIZE 256

CSystemInfo::CSystemInfo()
{
#ifdef WIN32
	// Windows
	this->OperatingSystem = L"Windows";
	this->Manufactory = L"Microsoft";
	this->Product = L"<Failed to query system info>";
	this->Version = L"<Failed to query system info>";

	// Get Architecture
	{
		SYSTEM_INFO si;
		GetSystemInfo(&si);
	
		switch(si.wProcessorArchitecture)
		{
		case PROCESSOR_ARCHITECTURE_AMD64:
			this->Architecture = L"x64"; break;
		case PROCESSOR_ARCHITECTURE_IA64:
			this->Architecture = L"Intel Itanium Processor Family (IPF)"; break;
		case PROCESSOR_ARCHITECTURE_INTEL:
			this->Architecture = L"x86"; break;
		case PROCESSOR_ARCHITECTURE_UNKNOWN:
		default:
			this->Architecture = L"Unknown architecture"; break;
		}
	}

	// Get ComputerName
	{
		wchar_t szBuffer[SI_MAX_SIZE];
		DWORD dwSize = SI_MAX_SIZE;
		if(GetComputerNameW(szBuffer, &dwSize))
			this->ComputerName = szBuffer;
		else
			this->ComputerName = L"<Unknown>";
	}

	// Get Product and Version
	{
		DWORD dwRet, dwType=REG_SZ, dwSize;
		HKEY hKey;

		dwRet = RegOpenKeyW(HKEY_LOCAL_MACHINE,
					L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
					&hKey);
		if(dwRet != ERROR_SUCCESS)
		{
			LogError(_T("Cannot open registry to query system info"));
			return;
		}

		wchar_t buffer[SI_MAX_SIZE];

		// query Product Name -> Windows 7 Professional
		dwSize=SI_MAX_SIZE * sizeof(wchar_t);
		dwRet = RegQueryValueExW(hKey,
								 L"ProductName",
								 NULL,
								 &dwType,
								 (LPBYTE)buffer,
								 &dwSize);
		if(dwRet != ERROR_SUCCESS)
		{
			LogError(_T("Cannot query ProductName"));
			RegCloseKey(hKey);
			return;
		}
		this->Product = buffer;

		// query Version -> 6.1
		dwSize=SI_MAX_SIZE * sizeof(wchar_t);
		dwRet = RegQueryValueExW(hKey,
								 L"CurrentVersion",
								 NULL,
								 &dwType,
								 (LPBYTE)buffer,
								 &dwSize);
		if(dwRet != ERROR_SUCCESS)
		{
			LogError(_T("Cannot query CurrentVersion"));
			RegCloseKey(hKey);
			return;
		}
		this->Version = buffer;
		this->Version += L".";

		// query CurrentBuild -> 7600
		dwSize=SI_MAX_SIZE * sizeof(wchar_t);
		dwRet = RegQueryValueExW(hKey,
								 L"CurrentBuild",
								 NULL,
								 &dwType,
								 (LPBYTE)buffer,
								 &dwSize);
		if(dwRet != ERROR_SUCCESS)
		{
			LogError(_T("Cannot query CurrentBuild"));
			RegCloseKey(hKey);
			return;
		}
		this->Version += buffer;

		RegCloseKey(hKey);
	}
#else
	// Linux
	struct utsname buf;
	if(uname(&buf)==-1)
	{
		LogError("Cannot query SystemInfo");
		return;
	}
	else
	{
		OperatingSystem = buf.sysname;
		ComputerName = buf.nodename;
		Version = buf.release;
		Architecture = buf.machine;
	}
	ifstream is("/etc/issue");
	if(!is.is_open())
	{
		Product = "<Failed to query Product>";
	}
	else
	{
		char buffer[SI_MAX_SIZE];
		while(is.getline(buffer,SI_MAX_SIZE))
		{
			string sbuffer = string(buffer);
			if(sbuffer=="")
				continue;
			else
			{
				size_t top,end;
				end = sbuffer.find("\\");
				top = sbuffer.find("Welcome");
				if (end!=string::npos && top!=string::npos)
					Product = sbuffer.substr(top+11,end-top-11);
				else if(top!=string::npos)
					Product = sbuffer.substr(top+11);
				else if(end!=string::npos)
					Product = sbuffer.substr(0,end);
				else 
					Product = sbuffer;
			}
		}
		is.close();
	}	
#endif

}

CSystemInfo::~CSystemInfo()
{
}

ENDNS ENDNS
